package main.java.study.核酸结果仪器;

import main.java.study.核酸结果仪器.entity.DataValidity;
import main.java.study.核酸结果仪器.entity.ExperimentalData;
import main.java.study.核酸结果仪器.entity.HeaderData;
import org.apache.pdfbox.pdmodel.PDDocument;
import org.apache.pdfbox.text.PDFTextStripper;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

public class 解析PDF文件 {

    public static void main(String[] args) {
        System.out.println("解析PDF文件");
        try {
            // 加载PDF文件
            File file = new File("E:\\WeChat Files\\wxid_dwml989ttnvp22\\FileStorage\\File\\2024-10\\KN2403355.pdf");
            PDDocument document = PDDocument.load(file);

            // 创建PDFTextStripper对象，用于提取文本
            PDFTextStripper pdfStripper = new PDFTextStripper();

            // 获取PDF文档的文本内容
            String text = pdfStripper.getText(document);
            System.out.println("PDF文件内容：" + text);

            // 依据"Donor Result Report"分割字符串
            String[] split = text.split("Donor Result Report");

            // 处理表头信息
            HeaderData headerData = handleHeaderInformation(split[1]);

            // 处理标准格式文本的方法
            List<DataValidity> dataValidityList = workWithStandardFormatText(split[1]);

            // 处理实验数据
            List<ExperimentalData> experimentalDataList = processExperimentalData(text);

            System.out.println("最后结果headerData：\n" + headerData + "\ndataValidityList：\n" + dataValidityList
                + "\nexperimentalDataList：\n" + experimentalDataList);

            // 输出文本
            // System.out.println("PDF文件内容：\n" + text);

            // 关闭文档
            document.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 处理表头信息
     * 
     * @param data 表头数据
     * @return HeaderData处理完的表头数据
     */
    private static HeaderData handleHeaderInformation(String data) {
        Pattern pattern = Pattern.compile(
            "USA(.*?)Control Inval.Channel 4Channel 3Channel 2Channel 1Control ID RMECControlS-Tube ID ControlSK24",
            Pattern.DOTALL);
        Matcher matcher1 = pattern.matcher(data);
        String headerInformation = null;
        while (matcher1.find()) {
            headerInformation = matcher1.group(1).trim();
            // System.out.println("表头数据：" + headerInformation);
        }
        String[] split1 = headerInformation.split("\r\n");
        HeaderData headerData = new HeaderData();

        // 头部信息第一段
        String[] split3 = split1[1].split("Pooling Date: |STAR S/N:|Batch ID: |PDM SW:");
        headerData.setPoolingDate(split3[0]);
        headerData.setSTARSN(split3[1]);
        headerData.setBatchId(split3[2]);
        headerData.setPDMSW(split3[3]);

        // 头部信息第二段
        String[] split4 = split1[2].split("Testing Date: |CAP S/N:|Test: |User:");
        headerData.setTestingDate(split4[0]);
        headerData.setCAPSN(split4[1]);
        headerData.setTest(split4[2]);
        headerData.setUser(split4[3]);

        // 头部信息第三段
        String[] split5 = split1[3].split("CTM S/N:|Reagents Kit Lot ID:|Batch Status:");
        headerData.setCTMSN(split5[0]);
        headerData.setReagentsKitLotId(split5[1]);
        headerData.setBatchStatus(split5[2]);

        // 头部信息第四段
        String[] split6 = split1[4].split("SK24 ID: |- Expiration Date:");
        headerData.setSK24Id(split6[0]);
        headerData.setExpirationDate(split6[1]);

        // System.out.println("处理完的表头数据：" + headerData);
        return headerData;
    }

    /**
     * 处理实验数据的方法
     * 
     * @param text 整体pdf文本
     * @return 实验数据列表
     */
    private static List<ExperimentalData> processExperimentalData(String text) {

        StringBuilder testResult = new StringBuilder();
        String regex = "Flags StatusType \\(Date/Time\\)Pos(.*?)\\(Report Revision 4\\)";
        Pattern pattern = Pattern.compile(regex, Pattern.DOTALL);
        Matcher matcher = pattern.matcher(text);
        // 循环查找所有匹配的内容
        while (matcher.find()) {
            String group = matcher.group(1).trim();
            testResult.append("\r\n" + group);
        }
        // System.out.println("实验数据：\n" + testResult);

        // 分隔符正则表达式
        String regex1 = "(?m)^(Accepted|Created).*";
        Pattern pattern1 = Pattern.compile(regex1);
        Matcher matcher1 = pattern1.matcher(testResult.toString());

        List<String> splitResults = new ArrayList<>();
        int lastMatchEnd = 0;

        // 查找匹配项并保留分隔符
        while (matcher1.find()) {
            // 获取当前匹配项
            String matchedDelimiter = matcher1.group();

            // 将上一个匹配结束到当前匹配开始之间的内容添加到结果列表
            if (lastMatchEnd < matcher1.start()) {
                String substring = testResult.substring(lastMatchEnd, matcher1.end());

                splitResults.add(substring);
            }

            // 更新最后匹配结束位置
            lastMatchEnd = matcher1.end();
        }

        List<ExperimentalData> experimentalDataList = new ArrayList<>();
        // 输出结果
        for (String result : splitResults) {

            if (result.contains("Reactive")) {
                continue;
            }
            // System.out.println("分割后的实验数据：\n" + result.trim());
            String[] rows = result.trim().split("\r\n");

            // System.out.println("rows.length:" + rows.length);
            String[] split1 = rows[0].split("(?<=N/A)");
            String s = split1[0];
            String s1 = split1[1] + rows[1];
            String s2 = rows[2] + rows[3];
            String s3 = rows[4] + rows[5];
            String s4 = rows[6] + rows[7];
            String s5 = rows[8];
            String s6 = rows[9];

            String[] split2 = rows[10].split("\\s");
            String s7 = split2[0];
            String[] split3 = split2[1].split("(?<=N.R.)");
            String s8 = split3[0];
            String s9 = split3[1];
            String s10 = split2[2];

            // System.out.println("rows[11]:" + rows[11]);
            String[] split4 = rows[11].split("(?<=N.R.)");
            String s11 = split4[0];
            String s12 = split4[1];
            String[] split5 = s12.split(",");
            List<String> list = Arrays.stream(split5).map(String::trim).collect(Collectors.toList());
            ExperimentalData experimentalData = new ExperimentalData();
            experimentalData.setInvalFlags(s);
            experimentalData.setChannel4(s1);
            experimentalData.setChannel3(s2);
            experimentalData.setChannel2(s3);
            experimentalData.setChannel1(s4);
            experimentalData.setAcceptedOperator(s5);
            experimentalData.setDateTime(s6);
            experimentalData.setPoolingType(s7);
            experimentalData.setResult(s8);
            experimentalData.setSK24Pos(s9);
            experimentalData.setSTubeId(s10);
            experimentalData.setDonorStatus(s11);
            experimentalData.setDonorIds(list);
            // 换行输出以上数据
            experimentalDataList.add(experimentalData);
            // System.out.println("开始输出experimentalData：" + experimentalData.toString());
        }
        return experimentalDataList;
    }

    /**
     * 处理标准格式文本的方法
     * 
     * @param split 包含标准格式文本
     * @return 标准性数据列表
     */
    private static List<DataValidity> workWithStandardFormatText(String split) {
        // 取"FlagsName StatusLot Number Exp. DatePos"与"Inval.Channel 4Channel 3Channel 2Channel 1 Accepted
        // OperatorPooling DonorS-Tube ID ResultSK24"之间的字符串
        String standardText = split.substring(split.indexOf("FlagsName StatusLot Number Exp. DatePos") + 39, split
            .indexOf("Inval.Channel 4Channel 3Channel 2Channel 1 Accepted OperatorPooling DonorS-Tube ID ResultSK24"));
        // 输出标准格式文本
        // System.out.println("标准格式文本：\n" + standardText);

        // 1. 按行分割字符串
        String[] lines = standardText.split("\n");
        // 2. 取出标准性数据行
        String[] validLines = new String[lines.length - 1];
        for (int i = 1; i < lines.length; i++) {
            validLines[i - 1] = lines[i];
        }
        // 3. 分割标准性数据行
        String[][] data = new String[validLines.length][];
        for (int i = 0; i < validLines.length; i++) {
            // 用于处理有效行数据的字符串，替换特定标记
            String tempData = validLines[i].replace(": ", "<COLON>").replace("Valid (", "<COLON2>")
                .replace(" (", "<COLON3>").replace("HIV-1 O", "<COLON4>");

            // 按空格分割其余部分，(?<=\\)) 是一个正向前瞻断言，它表示在每个 ) 后进行分割，同时保留该 ) 符号。
            String[] parts = tempData.split("\\s+|(?<=\\))|(?<=N/A)|(?<=Valid)");

            ArrayList<String> result = new ArrayList<>();

            // 遍历分割后的部分，并将占位符替换回原来的 ": "
            for (String part : parts) {
                result.add(part.replace("<COLON>", ": ").replace("<COLON2>", "Valid (").replace("<COLON3>", " (")
                    .replace("<COLON4>", "HIV-1 O"));
            }
            data[i] = result.toArray(new String[0]);
        }
        // 4. 输出标准性数据
        List<DataValidity> dataValidityList = new ArrayList<>();
        for (int i = 0; i < data.length; i++) {
            // System.out.println("标准性数据：" + Arrays.toString(data[i]));
            // 封装到DataValidity对象中
            DataValidity validity = new DataValidity();
            validity.setChannel4(data[i][0]);
            validity.setChannel3(data[i][1]);
            validity.setChannel2(data[i][2]);
            validity.setChannel1(data[i][3]);
            validity.setInvalFlags(data[i][4]);
            validity.setControlId(data[i][5]);
            validity.setRMECStatus(data[i][6]);
            validity.setSK24Pos(data[i][7]);
            validity.setSTubeId(data[i][8]);
            validity.setControlName(data[i][9]);
            validity.setControlLotNumber(data[i][10]);
            validity.setControlExpDate(data[i][11]);
            dataValidityList.add(validity);
            // System.out.println(validity.toString());
        }
        return dataValidityList;
    }
}
